import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:htxd_flutter_mapbox_sdk/htxd_flutter_mapbox_sdk.dart';
import 'package:mapbox_maps_flutter/mapbox_maps_flutter.dart';

class MapBoxControl {
  late final MapboxMap _mapboxMap;
  late StyleManager _style;
  late AmapLocationControl _locationControl;

  // 空的 layer
  static const String EMPTY_LAYER = "empty_layer";

  // mapbox 注记
  // 注记 source 和 layer
  static const String _MAPBOX_ZHU_JI_SOURCE = "mapbox_zhu_ji_source";
  static const String _MAPBOX_ZHU_JI_LAYER = "mapbox_zhu_ji_layer";

  // 星图部分的地图和注记
  // 底图 source 和 layer
  static const String _XING_TU_STATELLITE_SOURCE = "xing_tu_statellite_source";
  static const String _XING_TU_STATELLITE_LAYER = "xing_tu_statellite_layer";

  // 注记 source 和 layer
  static const String _XING_TU_ZHU_JI_SOURCE = "xing_tu_zhu_ji_source";
  static const String _XING_TU_ZHU_JI_LAYER = "xing_tu_zhu_ji_layer";

  // 天地图部分
  // 底图 source 和 layer
  static const String _TDT_STATELLITE_SOURCE = "tdt_statellite_source";
  static const String _TDT_STATELLITE_LAYER = "tdt_statellite_layer";

  // 路网
  static const String _TDT_ROAD_SOURCE = "tdt_road_source";
  static const String _TDt_ROAD_LAYER = "tdt_road_layer";

  // 注记
  static const String _TDT_ZHU_JI_SOURCE = "tdt_zhu_ji_source";
  static const String _TDT_ZHU_JI_LAYER = "tdt_zhu_ji_layer";

  // 中心点 source 和 layer
  static const String _CURRENT_CENTER_SOURCE = "current_center_source";
  static const String _CURRENT_CENTER_LAYER = "current_center_layer";

  bool _isShow2D = true;
  ShowType showType = ShowType.XINGTU;

  late Null Function(dynamic message) listener;
  static double _currentZoom = 17;

  MapBoxControl(this._mapboxMap) {
    _style = _mapboxMap.style;
    _locationControl = AmapLocationControl(locationSuccess: (entity) {
      stopLocation();
      _moveToCenter(entity.position!);
      DrawLandWebSocketListener.endMove(ScreenCoordinate(
          x: double.tryParse("${entity.position!.lat}") ?? 0,
          y: double.tryParse("${entity.position!.lng}") ?? 0));
    });
    _style.setProjection('mercator');
    _addLayer();
    listener = (message) {
      if (message['type'] == "endMove") {
        _moveToCenter(Position(double.tryParse('${message['longitude']}') ?? 0,
            double.tryParse('${message['latitude']}') ?? 0));
      }
    };
    DrawLandWebSocketListener.addListener(listener);
  }

  // 添加各种layer
  void _addLayer() async {
    // 空的layer
    await _style.addLayer(BackgroundLayer(
        id: EMPTY_LAYER, backgroundColor: Colors.transparent.value));

    // mapbox 注记
    await _addRasterLayer(_MAPBOX_ZHU_JI_SOURCE,
        Contract.XING_TU_ZHUJI_SOURCE_URL, _MAPBOX_ZHU_JI_LAYER);

    // 星图部分
    await _addRasterLayer(_XING_TU_STATELLITE_SOURCE,
        Contract.XING_TU_SATELLITE_SOURCE_URL, _XING_TU_STATELLITE_LAYER);
    await _addRasterLayer(_XING_TU_ZHU_JI_SOURCE,
        Contract.XING_TU_ZHUJI_SOURCE_URL, _XING_TU_ZHU_JI_LAYER);
  }

  /// 获取mapboxMap对象
  MapboxMap get mapboxMap => _mapboxMap;

  /// 隐藏 logo 等相关信息
  void hideMapLogo([bool isHideScaleBar = false]) async {
    _mapboxMap.logo.updateSettings(LogoSettings(
      marginLeft: ScreenUtil().screenWidth * 5,
      marginTop: ScreenUtil().screenHeight * 5,
    ));

    _mapboxMap.attribution.updateSettings(AttributionSettings(
      marginLeft: ScreenUtil().screenWidth * 5,
      marginTop: ScreenUtil().screenHeight * 5,
    ));
    if (isHideScaleBar) {
      _mapboxMap.compass.updateSettings(CompassSettings(enabled: false));
      _mapboxMap.scaleBar.updateSettings(ScaleBarSettings(enabled: false));
      GesturesSettings gesturesSettings =
          await _mapboxMap.gestures.getSettings();
      gesturesSettings.rotateEnabled = false;
      gesturesSettings.pitchEnabled = false;
      _mapboxMap.gestures.updateSettings(gesturesSettings);
    }
  }

  /// 获取中心点
  Future<Point> getCenter() async {
    var cameraState = await _mapboxMap.getCameraState();
    var center = cameraState.center;
    Map<String, dynamic> centerMap = {};
    center.forEach((key, value) {
      centerMap[key!] = value;
    });
    return Point.fromJson(centerMap);
  }

  /// 切换地图类型， 2D 和 3D切换
  void switchMapType() {
    _isShow2D = !_isShow2D;
    if (_isShow2D) {
      style.setProjection('mercator');
    } else {
      style.setProjection('globe');
    }
  }

  bool get isShow2D => _isShow2D;

  StyleManager get style => _style;

  /// 开始定位
  void startLocation() {
    _locationControl.startLocation();
  }

  /// 停止定位
  void stopLocation() {
    _locationControl.stopLocation();
  }

  /// 销毁方法
  Future<void> dispose() async {
    _locationControl.dispose();
  }

  Future<void> _moveToCenter(Position position) async {
    print("移动到：${position.lng}");
    print("移动到：${position.lat}");
    await moveToCenter(position);
    await removeLayerAndSource(_CURRENT_CENTER_LAYER, _CURRENT_CENTER_SOURCE);
    await _addCenter(position);
  }

  //移动某点到中心点
  Future<void> moveToCenter(Position position) async {
    await _mapboxMap.flyTo(
        CameraOptions(
          center: Point(coordinates: position).toJson(),
          zoom: _currentZoom,
        ),
        MapAnimationOptions(duration: 500));
  }

  Future<void> _addCenter(Position position) async {
    Feature<Point> feature =
        Feature(id: '', geometry: Point(coordinates: position));
    GeoJsonSource geoJsonSource = GeoJsonSource(
        id: _CURRENT_CENTER_SOURCE, data: jsonEncode(feature.toJson()));
    await style.addSource(geoJsonSource);
    CircleLayer circleLayer = CircleLayer(
        id: _CURRENT_CENTER_LAYER,
        sourceId: _CURRENT_CENTER_SOURCE,
        circleColor: Contract.CURRENT_LOCATION_COLOR.value,
        circleRadius: Contract.CURRENT_LOCATION_WIDTH,
        circleStrokeWidth: Contract.CURRENT_LOCATION_OUT_WIDTH,
        circleStrokeColor: Contract.CURRENT_LOCATION_OUT_COLOR.value);
    await style.addLayer(circleLayer);
  }

  // 天际 raster 类型的source 和 layer
  Future<void> _addRasterLayer(
      String sourceId, String url, String layerId) async {
    if (await _style.styleSourceExists(sourceId) == false) {
      RasterSource source =
          RasterSource(id: sourceId, tileSize: 256, tiles: [url], maxzoom: 17);
      await _style.addSource(source);
    }
    if (await _style.styleLayerExists(layerId) == false) {
      RasterLayer layer = RasterLayer(id: layerId, sourceId: sourceId);
      await _style.addLayerAt(layer, LayerPosition(below: EMPTY_LAYER));
    }
  }

  /// 屏幕坐标 转 经纬度坐标
  Future<Position> screenToPosition(ScreenCoordinate screenCoordinate) async {
    var map = await _mapboxMap.coordinateForPixel(screenCoordinate);
    var object = map['coordinates']! as List;
    return Position((object[0] as num), (object[1] as num));
  }

  /// 经纬度坐标转屏幕坐标点 但是如果是需要拿着坐标进行地图查询的话，则不需要进行转化处理
  Future<ScreenCoordinate> positionToScreen(Position position,
      {bool isMapToQuery = false}) async {
    List<Map<String, dynamic>> points = [];
    points.add(Point(coordinates: position).toJson());
    var screenCoordinates = await _mapboxMap.pixelsForCoordinates(points);
    var screenCoordinate = screenCoordinates[0];
    if (isMapToQuery) {
      return ScreenCoordinate(x: screenCoordinate!.x, y: screenCoordinate.y);
    } else {
      return ScreenCoordinate(
          x: screenCoordinate!.x / MyScreenUtil.pixelRatio,
          y: screenCoordinate.y / MyScreenUtil.pixelRatio);
    }
  }

  /// 显示天地图layer
  Future<void> _showTdtLayer() async {
    await removeLayerAndSource(
        _XING_TU_STATELLITE_LAYER, _XING_TU_STATELLITE_SOURCE);
    await removeLayerAndSource(_XING_TU_ZHU_JI_LAYER, _XING_TU_ZHU_JI_SOURCE);
    // 天地图部分
    await _addRasterLayer(_TDT_STATELLITE_SOURCE,
        Contract.TDT_SATELLITE_SOURCE_URL, _TDT_STATELLITE_LAYER);
    await _addRasterLayer(
        _TDT_ROAD_SOURCE, Contract.TDT_ROAD_SOURCE_URL, _TDt_ROAD_LAYER);
    await _addRasterLayer(
        _TDT_ZHU_JI_SOURCE, Contract.TDT_ZHU_JI_SOURCE_URL, _TDT_ZHU_JI_LAYER);
  }

  /// 显示星图layer
  Future<void> _showXingTuLayer() async {
    await removeLayerAndSource(_TDT_STATELLITE_LAYER, _TDT_STATELLITE_SOURCE);
    await removeLayerAndSource(_TDt_ROAD_LAYER, _TDT_ROAD_SOURCE);
    await removeLayerAndSource(_TDT_ZHU_JI_LAYER, _TDT_ZHU_JI_SOURCE);
    await _addRasterLayer(_XING_TU_STATELLITE_SOURCE,
        Contract.XING_TU_SATELLITE_SOURCE_URL, _XING_TU_STATELLITE_LAYER);
    await _addRasterLayer(_XING_TU_ZHU_JI_SOURCE,
        Contract.XING_TU_ZHUJI_SOURCE_URL, _XING_TU_ZHU_JI_LAYER);
  }

  /// 显示和mapboxLayer
  Future<void> _showMapboxLayer() async {
    await removeLayerAndSource(
        _XING_TU_STATELLITE_LAYER, _XING_TU_STATELLITE_SOURCE);
    await removeLayerAndSource(_XING_TU_ZHU_JI_LAYER, _XING_TU_ZHU_JI_SOURCE);
    await removeLayerAndSource(_TDT_STATELLITE_LAYER, _TDT_STATELLITE_SOURCE);
    await removeLayerAndSource(_TDt_ROAD_LAYER, _TDT_ROAD_SOURCE);
    await removeLayerAndSource(_TDT_ZHU_JI_LAYER, _TDT_ZHU_JI_SOURCE);
  }

  void showTypeLayer(ShowType type) {
    showType = type;
    switch (showType) {
      case ShowType.MAPBOX:
        _showMapboxLayer();
        break;
      case ShowType.TDT:
        _showTdtLayer();
        break;
      case ShowType.XINGTU:
        _showXingTuLayer();
        break;
    }
  }

  // 移除layer
  Future<void> removeLayer(String layerId) async {
    if (await _style.styleLayerExists(layerId) == true) {
      await _style.removeStyleLayer(layerId);
    }
  }

  // 移除layer
  Future<void> removeLayerAndSource(String layerId, String sourceId) async {
    if (await _style.styleLayerExists(layerId) == true) {
      await _style.removeStyleLayer(layerId);
    }
    if (await _style.styleSourceExists(sourceId) == true) {
      await _style.removeStyleSource(sourceId);
    }
  }
}

/// 显示类型
enum ShowType { MAPBOX, TDT, XINGTU }
